#include "OthelloGameRule.h"
#include "OthelloPlayer.h"
#include <iostream>
#include <vector>

bool OthelloGameRule::checkAddPoint(QPoint & qPoint,Player* player){
    if(((*_chessBoardArray)[qPoint.x()][qPoint.y()]==NULL) && (eatNum(qPoint,player)>0)){
        return true;
    }
    else
        return false;
}
void OthelloGameRule::eatByDirect(QPoint qPoint,int xd,int yd,Player* player){
    if(eatNumByDirect(qPoint,xd,yd,player)==0)
        return;
    int x,y;
    x = qPoint.x()+xd;
    y = qPoint.y()+yd;
    while(isInChessBoard(x,y)){
        if((*_chessBoardArray)[x][y]==NULL)
            break;
        if(!((*_chessBoardArray)[x][y]->getAttribute("owner")).compare(player->getSide())){
            return;
        }else{
            _chessBoard->setChess(QPoint(x,y),(player->getSide()));
        }
        x += xd;
        y += yd;
    }
    return;
}

void OthelloGameRule::putChess(std::vector<QPoint> * qPointList, Player * player){
    QPoint qPoint = qPointList->at(0);
    eatByDirect(qPoint,-1,0,player);
    eatByDirect(qPoint,-1,1,player);
    eatByDirect(qPoint,0,1,player);
    eatByDirect(qPoint,1,1,player);
    eatByDirect(qPoint,1,0,player);
    eatByDirect(qPoint,1,-1,player);
    eatByDirect(qPoint,0,-1,player);
    eatByDirect(qPoint,-1,-1,player);
    _chessBoard->setChess(qPoint,(player->getSide()));
    updateScore();
    return;
}


bool OthelloGameRule::isWin(){

    for(int i=0;i<_playerList->size();i++){
        if(isAvalible(_playerList->at(i)))
            return false;
    }
    return true;
}

bool OthelloGameRule::isInChessBoard(int x,int y){
    if(x>=0 && x<_chessBoard->getChessBoardLength() && y>=0 && y<_chessBoard->getChessBoardWidth())
        return true;
    else
        return false;
}

int OthelloGameRule::eatNumByDirect(QPoint qPoint,int xd,int yd,Player* player){
    int x,y,eatNum=0;
    x = qPoint.x()+xd;
    y = qPoint.y()+yd;
    while(isInChessBoard(x,y)){
        if((*_chessBoardArray)[x][y]==NULL)
            break;
        if(!((*_chessBoardArray)[x][y]->getAttribute("owner")).compare(player->getSide())){
            return eatNum;
        }else{
            eatNum++;
        }
        x += xd;
        y += yd;
    }
    return 0;
}
int OthelloGameRule::eatNum(QPoint & qPoint,Player* player){
    int totalEatNum =0;
    totalEatNum+=eatNumByDirect(qPoint,-1,0,player);
    totalEatNum+=eatNumByDirect(qPoint,-1,1,player);
    totalEatNum+=eatNumByDirect(qPoint,0,1,player);
    totalEatNum+=eatNumByDirect(qPoint,1,1,player);
    totalEatNum+=eatNumByDirect(qPoint,1,0,player);
    totalEatNum+=eatNumByDirect(qPoint,1,-1,player);
    totalEatNum+=eatNumByDirect(qPoint,0,-1,player);
    totalEatNum+=eatNumByDirect(qPoint,-1,-1,player);
    return totalEatNum;
}

bool  OthelloGameRule::isAvalible(Player* player){
    for(int i=0;i<_chessBoard->getChessBoardLength();i++){
        for(int j=0;j<_chessBoard->getChessBoardWidth();j++){
            if(checkAddPoint(QPoint(i,j),player))
                return true;
        }
    }
    return false;
}
void OthelloGameRule::updateScore(){
    for(int i=0;i<_playerList->size();i++){

        (dynamic_cast<OthelloPlayer*>((*_playerList)[i]))->setScore(getScore((*_playerList)[i]));
    }
}

int OthelloGameRule::getScore(Player * player){
    int score = 0;

    for(int i=0;i<_chessBoard->getChessBoardLength();i++){
        for(int j=0;j<_chessBoard->getChessBoardWidth();j++){
            if((*_chessBoardArray)[i][j]!=NULL){
                if(!((*_chessBoardArray)[i][j]->getAttribute("owner")).compare(player->getSide())){
                    score++;
                }
            }

        }
    }
    std::cout<<"score: "<<score<<std::endl;
    return score;
}
Player* OthelloGameRule::getFirstPlayer(){
    return _playerList->at(0);
}

Player* OthelloGameRule::getNextPlayer(Player * lastPlayer){
    std::vector<Player*>::iterator it;
    it = std::find(_playerList->begin(),_playerList->end(),lastPlayer);
    int playerNo = it-(_playerList->begin());

    int currentPlayerNo = (playerNo+1)%_playerList->size();
    while(1){
        if(isAvalible(_playerList->at(currentPlayerNo))){
            return _playerList->at(currentPlayerNo);
        }
        if(currentPlayerNo==playerNo)
            break;
        currentPlayerNo = (currentPlayerNo+1)%_playerList->size();
    }

    //std::cout<<"null"<<std::endl;
    return NULL;

}
